home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
748
/
748.xpi
/
content
/
config.js
< prev
next >
Wrap
Text File
|
2010-02-11
|
21KB
|
643 lines
function Config() {
this._scripts = null;
this._configFile = this._scriptDir;
this._configFile.append("config.xml");
this._initScriptDir();
this._observers = [];
this._updateVersion();
this._load();
}
Config.prototype = {
addObserver: function(observer, script) {
var observers = script ? script._observers : this._observers;
observers.push(observer);
},
removeObserver: function(observer, script) {
var observers = script ? script._observers : this._observers;
var index = observers.indexOf(observer);
if (index == -1) throw new Error("Observer not found");
observers.splice(index, 1);
},
_notifyObservers: function(script, event, data) {
var observers = this._observers.concat(script._observers);
for (var i = 0, observer; observer = observers[i]; i++) {
observer.notifyEvent(script, event, data);
}
},
_changed: function(script, event, data) {
this._save();
this._notifyObservers(script, event, data);
},
installIsUpdate: function(script) {
return this._find(script) > -1;
},
_find: function(aScript) {
namespace = aScript._namespace.toLowerCase();
name = aScript._name.toLowerCase();
for (var i = 0, script; script = this._scripts[i]; i++) {
if (script._namespace.toLowerCase() == namespace
&& script._name.toLowerCase() == name) {
return i;
}
}
return -1;
},
_load: function() {
var domParser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
.createInstance(Components.interfaces.nsIDOMParser);
var configContents = getContents(this._configFile);
var doc = domParser.parseFromString(configContents, "text/xml");
var nodes = doc.evaluate("/UserScriptConfig/Script", doc, null, 0, null);
this._scripts = [];
for (var node = null; node = nodes.iterateNext(); ) {
var script = new Script(this);
for (var i = 0, childNode; childNode = node.childNodes[i]; i++) {
switch (childNode.nodeName) {
case "Include":
script._includes.push(childNode.firstChild.nodeValue);
break;
case "Exclude":
script._excludes.push(childNode.firstChild.nodeValue);
break;
case "Require":
var scriptRequire = new ScriptRequire(script);
scriptRequire._filename = childNode.getAttribute("filename");
script._requires.push(scriptRequire);
break;
case "Resource":
var scriptResource = new ScriptResource(script);
scriptResource._name = childNode.getAttribute("name");
scriptResource._filename = childNode.getAttribute("filename");
scriptResource._mimetype = childNode.getAttribute("mimetype");
scriptResource._charset = childNode.getAttribute("charset");
script._resources.push(scriptResource);
break;
case "Unwrap":
script._unwrap = true;
break;
}
}
script._filename = node.getAttribute("filename");
script._name = node.getAttribute("name");
script._namespace = node.getAttribute("namespace");
script._description = node.getAttribute("description");
script._enabled = node.getAttribute("enabled") == true.toString();
script._basedir = node.getAttribute("basedir") || ".";
this._scripts.push(script);
}
},
_save: function() {
var doc = Components.classes["@mozilla.org/xmlextras/domparser;1"]
.createInstance(Components.interfaces.nsIDOMParser)
.parseFromString("<UserScriptConfig></UserScriptConfig>", "text/xml");
for (var i = 0, scriptObj; scriptObj = this._scripts[i]; i++) {
var scriptNode = doc.createElement("Script");
for (var j = 0; j < scriptObj._includes.length; j++) {
var includeNode = doc.createElement("Include");
includeNode.appendChild(doc.createTextNode(scriptObj._includes[j]));
scriptNode.appendChild(doc.createTextNode("\n\t\t"));
scriptNode.appendChild(includeNode);
}
for (var j = 0; j < scriptObj._excludes.length; j++) {
var excludeNode = doc.createElement("Exclude");
excludeNode.appendChild(doc.createTextNode(scriptObj._excludes[j]));
scriptNode.appendChild(doc.createTextNode("\n\t\t"));
scriptNode.appendChild(excludeNode);
}
for (var j = 0; j < scriptObj._requires.length; j++) {
var req = scriptObj._requires[j];
var resourceNode = doc.createElement("Require");
resourceNode.setAttribute("filename", req._filename);
scriptNode.appendChild(doc.createTextNode("\n\t\t"));
scriptNode.appendChild(resourceNode);
}
for (var j = 0; j < scriptObj._resources.length; j++) {
var imp = scriptObj._resources[j];
var resourceNode = doc.createElement("Resource");
resourceNode.setAttribute("name", imp._name);
resourceNode.setAttribute("filename", imp._filename);
resourceNode.setAttribute("mimetype", imp._mimetype);
if (imp._charset) {
resourceNode.setAttribute("charset", imp._charset);
}
scriptNode.appendChild(doc.createTextNode("\n\t\t"));
scriptNode.appendChild(resourceNode);
}
if (scriptObj._unwrap) {
scriptNode.appendChild(doc.createTextNode("\n\t\t"));
scriptNode.appendChild(doc.createElement("Unwrap"));
}
scriptNode.appendChild(doc.createTextNode("\n\t"));
scriptNode.setAttribute("filename", scriptObj._filename);
scriptNode.setAttribute("name", scriptObj._name);
scriptNode.setAttribute("namespace", scriptObj._namespace);
scriptNode.setAttribute("description", scriptObj._description);
scriptNode.setAttribute("enabled", scriptObj._enabled);
scriptNode.setAttribute("basedir", scriptObj._basedir);
doc.firstChild.appendChild(doc.createTextNode("\n\t"));
doc.firstChild.appendChild(scriptNode);
}
doc.firstChild.appendChild(doc.createTextNode("\n"));
var configStream = getWriteStream(this._configFile);
Components.classes["@mozilla.org/xmlextras/xmlserializer;1"]
.createInstance(Components.interfaces.nsIDOMSerializer)
.serializeToStream(doc, configStream, "utf-8");
configStream.close();
},
parse: function(source, uri) {
var ioservice = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var script = new Script(this);
script._downloadURL = uri.spec;
script._enabled = true;
// read one line at a time looking for start meta delimiter or EOF
var lines = source.match(/.+/g);
var lnIdx = 0;
var result = {};
var foundMeta = false;
while ((result = lines[lnIdx++])) {
if (result.indexOf("// ==UserScript==") == 0) {
foundMeta = true;
break;
}
}
// gather up meta lines
if (foundMeta) {
// used for duplicate resource name detection
var previousResourceNames = {};
while ((result = lines[lnIdx++])) {
if (result.indexOf("// ==/UserScript==") == 0) {
break;
}
var match = result.match(/\/\/ \@(\S+)(?:\s+([^\n]+))?/);
if (match === null) continue;
var header = match[1];
var value = match[2];
if (value) { // @header <value>
switch (header) {
case "name":
case "namespace":
case "description":
script["_" + header] = value;
break;
case "include":
script._includes.push(value);
break;
case "exclude":
script._excludes.push(value);
break;
case "require":
var reqUri = ioservice.newURI(value, null, uri);
var scriptRequire = new ScriptRequire(script);
scriptRequire._downloadURL = reqUri.spec;
script._requires.push(scriptRequire);
break;
case "resource":
var res = value.match(/(\S+)\s+(.*)/);
if (res === null) {
// NOTE: Unlocalized strings
throw new Error("Invalid syntax for @resource declaration '" +
value + "'. Resources are declared like: " +
"@resource <name> <url>.");
}
var resName = res[1];
if (previousResourceNames[resName]) {
throw new Error("Duplicate resource name '" + resName + "' " +
"detected. Each resource must have a unique " +
"name.");
} else {
previousResourceNames[resName] = true;
}
var resUri = ioservice.newURI(res[2], null, uri);
var scriptResource = new ScriptResource(script);
scriptResource._name = resName;
scriptResource._downloadURL = resUri.spec;
script._resources.push(scriptResource);
break;
}
} else { // plain @header
switch (header) {
case "unwrap":
script._unwrap = true;
break;
}
}
}
}
// if no meta info, default to reasonable values
if (script._name == null) script._name = parseScriptName(uri);
if (script._namespace == null) script._namespace = uri.host;
if (!script._description) script._description = "";
if (script._includes.length == 0) script._includes.push("*");
return script;
},
install: function(script) {
GM_log("> Config.install");
var existingIndex = this._find(script);
if (existingIndex > -1) {
this.uninstall(this._scripts[existingIndex], false);
}
script._initFile(script._tempFile);
script._tempFile = null;
for (var i = 0; i < script._requires.length; i++) {
script._requires[i]._initFile();
}
for (var i = 0; i < script._resources.length; i++) {
script._resources[i]._initFile();
}
this._scripts.push(script);
this._changed(script, "install", null);
GM_log("< Config.install");
},
uninstall: function(script, uninstallPrefs) {
var idx = this._find(script);
this._scripts.splice(idx, 1);
this._changed(script, "uninstall", null);
// watch out for cases like basedir="." and basedir="../gm_scripts"
if (!script._basedirFile.equals(this._scriptDir)) {
// if script has its own dir, remove the dir + contents
script._basedirFile.remove(true);
} else {
// if script is in the root, just remove the file
script._file.remove(false);
}
if (uninstallPrefs) {
// Remove saved preferences
GM_prefRoot.remove("scriptvals." + script._namespace + "/" + script._name + ".");
}
},
/**
* Moves an installed user script to a new position in the array of installed scripts.
*
* @param script The script to be moved.
* @param destination Can be either (a) a numeric offset for the script to be
* moved or (b) another installet script to which position
* the script will be moved.
*/
move: function(script, destination) {
var from = this._scripts.indexOf(script);
var to = -1;
// Make sure the user script is installed
if (from == -1) return;
if (typeof destination == "number") { // if destination is an offset
to = from + destination;
to = Math.max(0, to);
to = Math.min(this._scripts.length - 1, to);
} else { // if destination is a script object
to = this._scripts.indexOf(destination);
}
if (to == -1) return;
var tmp = this._scripts.splice(from, 1)[0];
this._scripts.splice(to, 0, tmp);
this._changed(script, "move", to);
},
get _scriptDir() {
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsILocalFile);
file.append("gm_scripts");
return file;
},
/**
* Create an empty configuration if none exist.
*/
_initScriptDir: function() {
var dir = this._scriptDir;
if (!dir.exists()) {
dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
var configStream = getWriteStream(this._configFile);
var xml = "<UserScriptConfig/>";
configStream.write(xml, xml.length);
configStream.close();
}
},
get scripts() { return this._scripts.concat(); },
getMatchingScripts: function(testFunc) { return this._scripts.filter(testFunc); },
/**
* Checks whether the version has changed since the last run and performs
* any necessary upgrades.
*/
_updateVersion: function() {
log("> GM_updateVersion");
// this is the last version which has been run at least once
var initialized = GM_prefRoot.getValue("version", "0.0");
if ("0.0" == initialized) {
// this is the first launch. show the welcome screen.
// find an open window.
var windowManager = Components
.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator);
var chromeWin = windowManager.getMostRecentWindow("navigator:browser");
// if we found it, use it to open a welcome tab
if (chromeWin.gBrowser) {
// the setTimeout makes sure we do not execute too early -- sometimes
// the window isn't quite ready to add a tab yet
chromeWin.setTimeout(
"gBrowser.selectedTab = gBrowser.addTab(" +
"'http://wiki.greasespot.net/Welcome')", 0);
}
}
if (GM_compareVersions(initialized, "0.8") == -1)
this._pointEightBackup();
// update the currently initialized version so we don't do this work again.
var extMan = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
var item = extMan.getItemForID(GM_GUID);
GM_prefRoot.setValue("version", item.version);
log("< GM_updateVersion");
},
/**
* In Greasemonkey 0.8 there was a format change to the gm_scripts folder and
* testing found several bugs where the entire folder would get nuked. So we
* are paranoid and backup the folder the first time 0.8 runs.
*/
_pointEightBackup: function() {
var scriptDir = this._scriptDir;
var scriptDirBackup = scriptDir.clone();
scriptDirBackup.leafName += "_08bak";
if (scriptDir.exists() && !scriptDirBackup.exists())
scriptDir.copyTo(scriptDirBackup.parent, scriptDirBackup.leafName);
}
};
function Script(config) {
this._config = config;
this._observers = [];
this._downloadURL = null; // Only for scripts not installed
this._tempFile = null; // Only for scripts not installed
this._basedir = null;
this._filename = null;
this._name = null;
this._namespace = null;
this._description = null;
this._enabled = true;
this._includes = [];
this._excludes = [];
this._requires = [];
this._resources = [];
this._unwrap = false;
}
Script.prototype = {
matchesURL: function(url) {
function test(page) {
return convert2RegExp(page).test(url);
}
return this._includes.some(test) && !this._excludes.some(test);
},
_changed: function(event, data) { this._config._changed(this, event, data); },
get name() { return this._name; },
get namespace() { return this._namespace; },
get description() { return this._description; },
get enabled() { return this._enabled; },
set enabled(enabled) { this._enabled = enabled; this._changed("edit-enabled", enabled); },
get includes() { return this._includes.concat(); },
get excludes() { return this._excludes.concat(); },
addInclude: function(url) { this._includes.push(url); this._changed("edit-include-add", url); },
removeIncludeAt: function(index) { this._includes.splice(index, 1); this._changed("edit-include-remove", index); },
addExclude: function(url) { this._excludes.push(url); this._changed("edit-exclude-add", url); },
removeExcludeAt: function(index) { this._excludes.splice(index, 1); this._changed("edit-exclude-remove", index); },
get requires() { return this._requires.concat(); },
get resources() { return this._resources.concat(); },
get unwrap() { return this._unwrap; },
get _file() {
var file = this._basedirFile;
file.append(this._filename);
return file;
},
get editFile() { return this._file; },
get _basedirFile() {
var file = this._config._scriptDir;
file.append(this._basedir);
file.normalize();
return file;
},
get fileURL() { return GM_getUriFromFile(this._file).spec; },
get textContent() { return getContents(this._file); },
_initFileName: function(name, useExt) {
var ext = "";
name = name.toLowerCase();
var dotIndex = name.lastIndexOf(".");
if (dotIndex > 0 && useExt) {
ext = name.substring(dotIndex + 1);
name = name.substring(0, dotIndex);
}
name = name.replace(/\s+/g, "_").replace(/[^-_A-Z0-9]+/gi, "");
ext = ext.replace(/\s+/g, "_").replace(/[^-_A-Z0-9]+/gi, "");
// If no Latin characters found - use default
if (!name) name = "gm_script";
// 24 is a totally arbitrary max length
if (name.length > 24) name = name.substring(0, 24);
if (ext) name += "." + ext;
return name;
},
_initFile: function(tempFile) {
var file = this._config._scriptDir;
var name = this._initFileName(this._name, false);
file.append(name);
file.createUnique(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
this._basedir = file.leafName;
file.append(name + ".user.js");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0644);
this._filename = file.leafName;
GM_log("Moving script file from " + tempFile.path + " to " + file.path);
file.remove(true);
tempFile.moveTo(file.parent, file.leafName);
},
get urlToDownload() { return this._downloadURL; },
setDownloadedFile: function(file) { this._tempFile = file; },
get previewURL() {
return Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService)
.newFileURI(this._tempFile).spec;
}
};
function ScriptRequire(script) {
this._script = script;
this._downloadURL = null; // Only for scripts not installed
this._tempFile = null; // Only for scripts not installed
this._filename = null;
}
ScriptRequire.prototype = {
get _file() {
var file = this._script._basedirFile;
file.append(this._filename);
return file;
},
get fileURL() { return GM_getUriFromFile(this._file).spec; },
get textContent() { return getContents(this._file); },
_initFile: function() {
var name = this._downloadURL.substr(this._downloadURL.lastIndexOf("/") + 1);
if(name.indexOf("?") > 0) {
name = name.substr(0, name.indexOf("?"));
}
name = this._script._initFileName(name, true);
var file = this._script._basedirFile;
file.append(name);
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0644);
this._filename = file.leafName;
GM_log("Moving dependency file from " + this._tempFile.path + " to " + file.path);
file.remove(true);
this._tempFile.moveTo(file.parent, file.leafName);
this._tempFile = null;
},
get urlToDownload() { return this._downloadURL; },
setDownloadedFile: function(file) { this._tempFile = file; }
};
function ScriptResource(script) {
this._script = script;
this._downloadURL = null; // Only for scripts not installed
this._tempFile = null; // Only for scripts not installed
this._filename = null;
this._mimetype = null;
this._charset = null;
this._name = null;
}
ScriptResource.prototype = {
get name() { return this._name; },
get _file() {
var file = this._script._basedirFile;
file.append(this._filename);
return file;
},
get textContent() { return getContents(this._file); },
get dataContent() {
var appSvc = Components.classes["@mozilla.org/appshell/appShellService;1"]
.getService(Components.interfaces.nsIAppShellService);
var window = appSvc.hiddenDOMWindow;
var binaryContents = getBinaryContents(this._file);
var mimetype = this._mimetype;
if (this._charset && this._charset.length > 0) {
mimetype += ";charset=" + this._charset;
}
return "data:" + mimetype + ";base64," +
window.encodeURIComponent(window.btoa(binaryContents));
},
_initFile: ScriptRequire.prototype._initFile,
get urlToDownload() { return this._downloadURL; },
setDownloadedFile: function(tempFile, mimetype, charset) {
this._tempFile = tempFile;
this._mimetype = mimetype;
this._charset = charset;
}
};